﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.ComponentModel;
using Engine.Entities.Character;
using Assets.components;
using Assets.Game.scripts;
using FrenzyIsland.UI;

namespace Game.Scripts.Managers { 
    [Serializable]
    public class BuildingManager : MonoBehaviour {

        private static BuildingManager singleton;

        public static BuildingManager instance {
            get {
                return BuildingManager.singleton;
            }
        }

        public VoxelWorld voxelWorld;
        public AstarPath pathfindObject;
        public GameObject resourceCollectedWidget;
        public GameObject UIBuildingPreviewWidget;
        public LayerMask layerToBeIgnoreBuildingPreview;

        public List<BuildingPrototype> prototypes;
        public GameObject selectorObject;
        public GameObject UIMenuSelectedBuilding;
        public UIAtlas iconAtlas;

        void Awake() {

            Debug.Log("Awake BuildingManager");

            if (BuildingManager.singleton != null) {
                DestroyImmediate(this);
            } else {
                BuildingManager.singleton = this;
            }

            for (int i = 0; i < this.prototypes.Count; i++) {
                BuildingPrototype prototype = this.prototypes[i];
                prototype.prototypeIndex = i;
                prototype.manager = this;
            }

            ////per test, riempie le risorse fino al 3 livello
            //foreach (BuildingPrototype prot in prototypes)
            //{
            //    for(int i = 1; i <= 3; i++)
            //    {
            //        BuildingPrototype.LevelCostsWrapper wrapper = new BuildingPrototype.LevelCostsWrapper();
            //        wrapper.resources.Add(new Resource(ResourceEnum.Stone, (uint)(10 * i)));
            //        wrapper.resources.Add(new Resource(ResourceEnum.Wood, (uint)(10 * i)));
            //        prot.buildingCostsPerLevel.Add(wrapper);

            //        BuildingPrototype.LevelCostsWrapper wrapperRefound = new BuildingPrototype.LevelCostsWrapper();
            //        wrapperRefound.resources.Add(new Resource(ResourceEnum.Stone, (uint)(10 * i / 2)));
            //        wrapperRefound.resources.Add(new Resource(ResourceEnum.Wood, (uint)(10 * i / 2)));
            //        prot.buildingRefoundPerLevel.Add(wrapperRefound);
            //    }
            //}
        }
        
        public int prototypeCount {
            get {
                return this.prototypes.Count;
            }
        }
        
        public BuildingPrototype getPrototypeByIndex(int index) {
            return this.prototypes[index];
        }
        
        public BuildingPrototype getPrototypeByName(string name) {
            BuildingPrototype prototype = null;

            foreach(BuildingPrototype p in this.prototypes){
                if(p.name.Equals(name)){
                    prototype = p;
                    break;
                }
            }

            return prototype;
        }

        private Vector3 pos = Vector3.zero;
        /// <summary>
        /// Crea un oggetto temporaneo e lo posiziona sul primo voxel disponibile
        /// partendo dal punto visualizzato dalla telecamera e il centro dell'isola
        /// Return:  true: Errore, false: OK 
        /// </summary>
        public GameObject StartBuildingMode(BuildingPrototype prototype)
        {
            GameObject ris = null;
            FrenzyIslandGenerator fig = voxelWorld.GetComponent<FrenzyIslandGenerator>();
            GuiManager guiManager = UIRoot.list[0].GetComponent<GuiManager>();
            
            //prendo la posizione guardata dalla telecamera
            pos = guiManager.GetCenterPointScreen();
            if (pos == Vector3.zero) return null;

            //mi sposto verso il centro cercando uno spazio almeno sulla terra per costruire
            int cont = 100;
            Vector3 destination = new Vector3(64, 0, 64);
            while (Distance(pos, destination) > 1 && cont > 0)
            {
                pos = Vector3.MoveTowards(pos, destination, 1);

                //chiedo l'altezza del voxel trovato
                int y = fig.getHeightVoxelAt((int)pos.x, (int)pos.z);

                if (y == -1) continue;         //valori fuori dal terreno

                if (!prototype.isBuildingAllowedAt( (int)pos.x, y, (int)pos.z) ) continue;

                //istanzia un prototipo, ma senza aggiungerlo tra gli edifici costruiti
                ris = prototype.InstantiateBuildingPreview( new Vector3((int)pos.x, y, (int)pos.z));

                break;
            }

            return ris;
        }

        private float Distance(Vector3 _a, Vector3 _b)
        {
            Vector3 a = new Vector3(_a.x, 0, _a.z);
            Vector3 b = new Vector3(_b.x, 0, _b.z);
            return Vector3.Distance(a, b);
        }

        void OnDrawGizmos()
        {
            if (pos == Vector3.zero) return;
            Gizmos.DrawLine(pos, pos + Vector3.up * 50);
        }

    }

    
}